package com.dizang.concise.mvc.aop;

import java.util.UUID;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.StopWatch;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.MDC;
import org.springframework.stereotype.Component;

import com.alibaba.fastjson.JSONObject;
import com.dizang.concise.mvc.common.util.ResponseEntity;
import com.dizang.concise.mvc.common.util.ValidateUtils;

import lombok.extern.slf4j.Slf4j;

@Aspect
@Component
@Slf4j
public class ContractAop {

    // 切入点
    @Pointcut("@within(com.dizang.concise.mvc.common.annotation.Contract)")
    public void pointCut() {
    }

    @Around("pointCut()")
    public Object doMethod(ProceedingJoinPoint pjp) throws Throwable {
        Object proceed = null;
        String cl = pjp.getSignature().getDeclaringTypeName();
        String string = pjp.getSignature().getName();
        Object[] args = pjp.getArgs();
        
        String traceId = UUID.randomUUID().toString().replace("-", "");
        if (StringUtils.isEmpty(MDC.get("traceId") )) {
            MDC.put("traceId", traceId);
        }

        log.info("请求接口类方法开始:{}.{},REST接口参数:{}",cl, string, JSONObject.toJSONString(args));
        StopWatch stopWatch = new StopWatch();
        // 在这里做校验参数
        String validateBean = ValidateUtils.validateBean(args[0]);
        if (StringUtils.isNotEmpty(validateBean)) {
            log.error(validateBean);
        	return ResponseEntity.illgalArgument(validateBean);
        }
        
        stopWatch.start();
        proceed = pjp.proceed();
        stopWatch.stop();
        log.info("REST接口类方法耗时:{}.{},{}ms", cl,string, stopWatch.getTime());
        return proceed;
    }

    // 例外通知
    @AfterThrowing(value = "pointCut()", throwing = "exc")
    public void finanlExce(JoinPoint joinPoint, Throwable exc) {
        String cl = joinPoint.getSignature().getDeclaringTypeName();
        String string = joinPoint.getSignature().getName();
        log.error("请求接口类方法异常:{}.{},错误信息:{},{}",cl, string, exc.getMessage(), exc);
        MDC.clear();
    }

    @AfterReturning(value = "pointCut()", returning = "rtv")
    public void afterRetuExce(JoinPoint joinPoint, Object rtv) {
        String cl = joinPoint.getSignature().getDeclaringTypeName();
        String string = joinPoint.getSignature().getName();
        log.info("请求接口类方法结束:{}.{},返回值:{}", cl,string, JSONObject.toJSONString(rtv));
        MDC.clear();
    }

}
